<?php
// +----------------------------------------------------------------------
// | 中犇单商户
// +----------------------------------------------------------------------
// | Copyright (c) 2019-2021 中犇科技 All rights reserved.
// +----------------------------------------------------------------------


namespace app\user\model;

use app\operation\model\SystemMessage;
use \think\Db;
use \app\user\model\User;
use \app\user\model\MoneyLog;

/**
 * 提现控制器
 * Class Withdraw
 * @package app\user\model
 * @author 刘明美 [ liumingmei@zhongbenjituan.com ]
 * @since 2019/4/3 18:31
 */
class Withdraw extends \think\Model
{

    protected $table = '__USER_WITHDRAW__';

    // 自动写入时间戳
    protected $autoWriteTimestamp = true;
    

    /**
     * 获取提现列表
     * @param array $map
     * @param array $order
     * @return bool|object|null
     * @author 晓风<215628355@qq.com>
     */
    public static function getList($map = '', $order = [], $is_import = false)
    {
        $resd = self::view('user_withdraw', true)
            //->view('user_withdraw_account', 'account_type,account_id,qrcode', 'user_withdraw.account_id = user_withdraw_account.id', 'left') //不要联表查，提现账户是提现时的账号，不能跟随账号的更新改变
            ->view('user', 'mobile,user_name,user_nickname', 'user_withdraw.user_id = user.id', 'left')       
            ->where($map)
            ->order($order);
        if ($is_import) {
            return $resd->select();
        } else {
            return $resd->paginate();
        }

    }
    
      /**
     * 获取详情
     * @param type $id
     * @return type
     */
    public static function getInfo($id){
        return self::view('user_withdraw', true)
            ->view('user', 'user_nickname,mobile,head_img', 'user_withdraw.user_id = user.id')  
            ->where("user_withdraw.id",$id)
            ->find();
    }


    /**
     * 审核拒绝回退
     * @param int $uid 会员ID
     * @param float $cash_fee 提现金额
     * @param int $aid 提现表ID
     * @param string $rason 拒绝原因
     * @return boolean
     * @throws \Exception
     * @author 晓风<215628355@qq.com>
     */
    public static function checkBack($uid, $cash_fee, $aid, $rason , $order_sn)
    {

        Db::startTrans();
        try {
            $ret = User::where('id', $uid)->where("freeze_money", 'egt', $cash_fee)->update([       
                'freeze_money' => ['dec', $cash_fee]
            ]);
            if (!$ret) {
                throw new \Exception(lang('更新会员冻结金额失败'));
            }
            $now_money = User::where('id', $uid)->value('user_money');

            $data = [
                'check_status' => 2,
                'check_reason' => $rason,
                'check_time' => time(),
            ];
            $result = self::where('id', $aid)->where("check_status", 0)->where("cash_status", 0)->update($data);
            if (!$result) {
                throw new \Exception(lang('更新记录失败'));
            }
            $moneylog = MoneyLog::changeMoney($uid, $now_money, $cash_fee, 5, $remark = lang('提现返还'), $order_sn);
            if (!$moneylog) {
                throw new \Exception(lang('金额回退失败'));
            }
            Db::commit();
            // return true;
        } catch (\Exception $e) {
            Db::rollback();
            return $e->getMessage();
        }
        return true;
    }

    /**
     * 转账失败回退
     * @param int $uid 会员ID
     * @param float $cash_fee 提现金额
     * @param int $aid 提现表ID
     * @param string $rason 失败原因
     * @return boolean
     * @throws \Exception
     * @author 晓风<215628355@qq.com>
     */
    public static function cashBack($uid, $cash_fee, $aid, $rason ,$order_sn)
    {

        Db::startTrans();
        try {
            $ret = User::where('id', $uid)->where("freeze_money", 'egt', $cash_fee)->update([       
                'freeze_money' => ['dec', $cash_fee]
            ]);
            
            if (!$ret) {
                throw new \Exception(lang('更新会员冻结金额失败'));
            }
            $now_money = User::where('id', $uid)->value('user_money');
          
            $data = [
                'cash_status' => 2,
                'cash_reason' => $rason,
                'cash_time' => time(),
            ];
            $result = self::where('id', $aid)->where("check_status", 1)->where("cash_status", 0)->update($data);
            if (!$result) {
                throw new \Exception(lang('更新记录失败'));
            }
            $moneylog = MoneyLog::changeMoney($uid, $now_money, $cash_fee, 5, $remark = lang('转账失败'), $order_sn);
            if (!$moneylog) {
                throw new \Exception(lang('金额回退失败'));
            }
            Db::commit();
            return true;
        } catch (\Exception $e) {
            Db::rollback();
            return $e->getMessage();
        }
    }

    /**
     * 转账成功 转出钱
     * @param array|object $info 提现表数据
     * @return boolean
     * @throws \Exception
     * @author 晓风<215628355@qq.com>
     */
    public static function cashSuccess($info, $is_auto)
    {

        $uid = $info['user_id'];
        $cash_fee = $info['cash_fee'];
        $aid = $info['id'];

        Db::startTrans();
        try {          
            $data = [
                'cash_status' => 1,
                'cash_time' => time(),
                'remark' => $info['remark'] ?? '',
                'is_auto' => $is_auto ? 1 : 0,
                'transfer_id' => $info['transfer_id'] ?? 0,
                'transfer_img' => $info['transfer_img'] ?? '',
            
            ];
            $result = self::where('id', $aid)->where("check_status", 1)->where("cash_status", 0)->update($data);          
            if (!$result) {
                throw new \Exception(lang('更新记录失败'));
            }            
            
           \app\operation\model\SystemMessage::create([
                "to_user_id"=> $uid, 
                "title"=>'提现消息',      
                "content"=>   lang('您的提现已转账').'：' . lang('提现金额').'：' . $cash_fee,    
                "msg_type"=>1,          
                "custom"=>json_encode(['type'=>'withdraw','id'=>    $aid])
            ]);           
            //是否执行自动提现
            if (!$is_auto) {
                goto E;
            }
            if(!$info['account_id']){
                throw new \Exception(lang('当前账户不支持自动提现'));
            }
            $order_id = '';
            //执行第三方自动提现脚本
            switch ($info['account_type']) {
                case 1:    
                    //注意 $info['account_id'] 需要OPENID 。绑定的是哪个平台appid，就调用哪个平台appid
                    //如果有多个平台openid( 如小程序 + 开放平台 可以增加一个account_type来确定)
                    $data = [
                        "openid" => $info['account_id'],
                        "amount" => $info['pay_fee'],//提现金额
                        "partner_trade_no" => $info['order_no'],
                        "re_user_name" => $info['true_name'],
                        "desc" => lang('提现转入') . $uid . '_'.lang('手续费').'￥' . $info['handling_fee']
                    ];
                    //下面是对应公众号的OPENID的实例
                    $result = addons_action("WeChat", "CodePay", "transfers", $data);
                    $condition = $result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS';
                    if ($condition) {//微信企业转账出错
                        throw new \Exception('微信转账出错' . json_encode($result, JSON_UNESCAPED_UNICODE));
                    }
                    $order_id = $result["payment_no"];
                    break;
                case 2 :
                    //支付宝       
                    $ret = addons_action("Alipay", 'Aop', 'AlipayFundTransToaccountTransferRequest', [
                        'payee_account' => $info['account_id'],
                        'amount' => $info['pay_fee'],
                        'out_trade_no' => $info['order_no'],
                        'alipay_username' => $info['true_name'],
                        'payer_show_name' => config('web_site_title'),
                        'remark' => lang('提现转入') . $uid . '_'.lang('手续费').'￥' . $info['handling_fee'],
                    ]);
                    $order_id = $ret['order_id'];
                    break;
                default :
                    throw new \Exception(lang('目前不支持此账户类型自动提现，请人工转账'));           
            }
            if ($order_id) {
                self::where('aid', $aid)->update(['transaction_id' => $order_id]);
            }
            E:
            Db::commit();          
            return true;//支付宝打款失败不报异常
        } catch (\Exception $e) {
            Db::rollback();
            return $e->getMessage();
        }
    }   
    /**
     * 申请提现
     * @param User $user 会员模型
     * @param float $money 提现金额
     * @param int $account_type 账户类型(账户类型 1 微信 2 支付宝 3 银行卡)
     * @throws \Exception
     */
    public static function addInfo(User $user, $money,int $account_type){
        $account = WithdrawAccount::where(['user_id' => $user['id'], 'account_type' => $account_type])->find();
        if(!$account){
            throw new \Exception(lang('未绑定提现账户'));
        }
        $count = self::where("user_id",$user["id"])->whereTime("create_time", "today")->count();
        $withdraw_count =  module_config("user.withdraw_count");
        if ($count >= $withdraw_count) {
            throw new \Exception(lang('您今日提现次数已用完'));
        }
       // 读取实时金额
        $now_money = $user['user_money'];//用户余额
         //后台配置的最低提现标准
       
        $min_money = module_config('user.min_withdraw_money');
        $max_money = module_config('user.max_withdraw_money');

         // 提现金额起提标准判断       
        if (bccomp($now_money , $min_money,2) < 0) {       
            throw new \Exception(lang('您的余额暂未达到提现标准')  .' ￥' .$min_money );
        }

        // 提现金额不能大于封顶
        if (bccomp($money , $max_money,2) > 0) {
            throw new \Exception(lang('单笔提现金额最高为') .' ￥' .$max_money );
        }
        // 提现金额不能溢出之上限
        if (bccomp($money , '99999999.99',2) > 0) {
            throw new \Exception(lang('单笔提现金额最高为') . ' ￥ 99999999.99');
        }

        // 提现金额最低标准判断
        if (bccomp($min_money , $money,2) > 0) {        
            throw new \Exception(lang('提现金额最低为') .' ￥' .$min_money );
        }
        // 提现金额不能溢出之下限
        if (bccomp(0 , $money,2) >= 0) {        
            throw new \Exception(lang('提现金额需为正数'));
        }
        // 提现金额不能大于余额
        if (bccomp($money , $now_money,2) > 0) {
            throw new \Exception(lang('余额不足，无法提现'));
        }        
            //提现余额为减法
        $tx_money = -$money;

        $order_no = get_order_sn('TX');
        
        // 变更余额记录
        $moneylog = MoneyLog::changeMoney($user['id'], $now_money, $tx_money, 4, $remark = lang('会员申请提现'), $order_no);
        if (!$moneylog) {
            throw new \Exception(lang('更改余额失败'));
        }
        //写入到冻结金额
        User::where("id",$user["id"])->setInc("freeze_money",$money); 
        
         //组合用户提现信息  
        $withdraw_data = [
            'user_id' => $user['id'],       
            'order_no' => $order_no,
            'cash_fee' => $money,
            'check_status' => 0,
            
            'account_type' => $account['account_type'],
            'account_id' => $account['account_id'],
            'true_name' => $account['true_name'] ,
            'cardname' => $account['cardname'],
            'cardbank' => $account['cardbank'],
            'qrcode' => $account['qrcode'],
            
            'create_time' => time(),
        ];
        //精度计算手续费
        $withdraw_handling_type = module_config('user.withdraw_handling_type');
        if ($withdraw_handling_type == 0) {
            //固定金额手续费
            $withdraw_handling_fee = module_config('user.withdraw_handling_fee');
        } else {
            //百分比手续费
            $withdraw_handling_fee = bcmul($money, module_config('user.withdraw_handling_fee') * 0.01, 2);
        }
        $withdraw_data['pay_fee'] = bcsub($money, $withdraw_handling_fee, 2);
        $withdraw_data['handling_fee'] = $withdraw_handling_fee;
        // 新增提现记录
        $withdraw =  self::create($withdraw_data);
        if (!$withdraw) {
            throw new \Exception(lang('创建提现记录失败'));
        }
        return $withdraw;
    }

}
